package com.lanou.list;

/**
 * 单向循环链表
 * @author zyj
 * @date 2022年05月18日 11:19
 */
public class CirleSingleLinkedList<E> extends AbstractList<E> implements List<E>{

    private Node<E> head;

    @Override
    public E get(int index) {
        Node<E> node = node(index);
        return node.item;
    }


    public Node<E> getHead(){
        return head;
    }

    @Override
    public E set(int index, E element) {
        Node<E> node = node(index);
        E oldItem = node.item;
        node.item = element;
        return oldItem;
    }

    @Override
    public void add(int index, E element) {
        if (size == 0){
            head = new Node<>(element,null);
            head.next = head;
            size++;
        }else if (index == 0){
            head = new Node<E>(element,head);
            size++;
            Node<E> tail = node(size-1);
            tail.next = head;

        }else {
            Node<E> prev = node(index - 1);
            prev.next = new Node<E>(element, prev.next);
            size++;
        }
    }

    @Override
    public E remove(int index) {
        rangeCheck(index);
        if (index == 0){
            E e = head.item;
            head = head.next;
            size--;
            Node<E> tail = node(size-1);
            tail.next = head;
            return e;
        }else {
            Node<E> prev = node(index - 1);
            Node<E> cur = prev.next;
            prev.next = prev.next.next;
            cur.next = null;
            size--;
            return cur.item;
        }
    }

    @Override
    public int indexOf(E element) {
        if (null == element) {
            for (int i = 0; i < size; i++) {
                Node<E> node = node(i);
                if (null == node.item) {
                    return i;
                }
            }
        }else {
            for (int i = 0; i < size; i++) {
                Node<E> node = node(i);
                if (element.equals(node.item)){
                    return i;
                }
            }
        }
        return -1;
    }

    @Override
    public void clear() {
       head = null;
    }

    private Node<E> node(int index) {
        Node<E> cur = head;
        for (int i = 0; i < index; i++) {
            cur = cur.next;
        }
        return cur;
    }

    private class Node<E>{
        E item;
        Node<E> next;

        public Node(E item,Node<E> next){
            this.item = item;
            this.next = next;
        }
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder("head→");
        for (int i = 0; i < size; i++) {
            sb.append(node(i).item).append("→");
        }

        sb.append(head.item);
        return sb.toString();
    }


    public static void main(String[] args) {
        CirleSingleLinkedList<Integer> list = new CirleSingleLinkedList<>();

        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        list.add(5);  // 1 2 3 4 5 1

        list.add(0,6);  //6 1 2 3 4 5 6
        list.add(7);// 6 1 2 3 4 5 7 6
        System.out.println(list.set(0, 8));// 8 1 2 3 4 5 7 8
        System.out.println(list.size()); //7
        System.out.println(list.indexOf(3));

        list.remove(0);//1 2 3 4 5 7 1
       list.remove(5);//1 2 3 4 5 1
        list.remove(2);
        System.out.println(list);
    }

    private void rangeCheck(int index) {
        int size = size();
        if (index < 0 || index >= size)
            throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
    }


}

